package com.lkd.plcs7.direct.s7;

import com.github.s7connector.api.DaveArea;
import com.github.s7connector.api.S7Connector;
import com.github.s7connector.api.S7Serializer;
import com.github.s7connector.api.factory.S7ConnectorFactory;
import com.github.s7connector.api.factory.S7SerializerFactory;

import java.io.IOException;
import java.math.BigInteger;
import java.nio.ByteBuffer;
import java.nio.charset.StandardCharsets;


public class s7connectorTest   {
    public S7Connector initConnect(){
        //PLC地址
        String ipAddress = "192.168.0.200";
        //默认端口
        int port = 102;
        int rack=0;
        int slot=1;
        int timeout=10000;
        S7Connector s7connector=
                S7ConnectorFactory
                        .buildTCPConnector()
                        .withHost(ipAddress)
                        .withPort(port) //optional
                        .withRack(rack) //optional
                        .withSlot(slot) //optional
                        .withTimeout(timeout) //连接超时时间
                        .build();
        S7Serializer s7Serializer2L = S7SerializerFactory.buildSerializer(s7connector);
        return s7connector;

    }

    /**
     * 读取PLC中的整型数据
     *
     **/
    public void testReadPlcIntData() {

        S7Connector s7Connector = initConnect();
        //第一个参数：DaveArea.DB 表示读取PLC的地址区域为DB
        //第二个参数：DB块地址，若plc中是DB1000，则填1000
        //第三个参数：数据长度
        //第四个参数：偏移量
        byte[] getBytes = s7Connector.read(DaveArea.DB, 150, 2, 0);

        Integer intData = new BigInteger(getBytes).intValue();
        System.out.println("getIntData:"+intData);
        try {
            s7Connector.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * 向PLC中写短整型(2字节，对应PLC INT类型)数据
     *
     **/
    public void testWritePlcShortIntData() {

        S7Connector s7Connector = initConnect();
        //第一个参数：DaveArea.DB 表示读取PLC的地址区域为DB
        //第二个参数：DB块地址，若plc中是DB1000，则填1000
        //第三个参数：偏移量
        //第四个参数：写入的数据 二进制数组byte[]
        short data=15;
        byte[] bytes = ByteBuffer.allocate(2).putShort(data).array();
        System.out.println("bytes length:"+bytes.length);
        s7Connector.write(DaveArea.DB,150, 0,bytes);
        try {
            s7Connector.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    /**
     * 向PLC中写整型(4字节，对应PLC DINT类型)数据
     *
     **/
    public void testWritePlcIntData() {

        S7Connector s7Connector = initConnect();
        //第一个参数：DaveArea.DB 表示读取PLC的地址区域为DB
        //第二个参数：DB块地址，若plc中是DB1000，则填1000
        //第三个参数：偏移量
        //第四个参数：写入的数据 二进制数组byte[]
        int data=15;
        byte[] bytes = ByteBuffer.allocate(4).putInt(data).array();
        System.out.println("bytes length:"+bytes.length);
        s7Connector.write(DaveArea.DB,6, 0,bytes);
        try {
            s7Connector.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }


    /**
     * 向PLC中读字符串
     约定协议: 对于字符串，第一个字节是总长度值，此值包括标志位，第二个字节是有效数据位，紧跟有效数据字节数。
     **/
    public void testReadPlcStrData() {

        S7Connector s7Connector = initConnect();
        //第一个参数：DaveArea.DB 表示读取PLC的地址区域为DB
        //第二个参数：DB块地址，若plc中是DB1000，则填1000
        //第三个参数：数据长度
        //第四个参数：偏移量
        byte[] getBytes = s7Connector.read(DaveArea.DB, 150, 10, 20);
        String retString="";
        if(getBytes!=null&&getBytes.length<3) {
            retString= new String(getBytes,StandardCharsets.US_ASCII);
        }else if(getBytes!=null)
        {
            int charCount=Integer.valueOf(getBytes[1]);//第一个字节是总长度，第二个字节是有效字节数，获取有效字节数
            StringBuilder stringBuilder=new StringBuilder(charCount);
            for(int i=0;i<charCount;i++){
                stringBuilder.append((char)getBytes[i+2]);
            }
            retString=stringBuilder.toString();

        }

        System.out.println("getStringData:"+retString);
        try {
            s7Connector.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    /**
     * 向PLC中写字符串
     约定协议: 对于字符串，第一个字节是总长度值，此值包括标志位，第二个字节是有效数据位，紧跟有效数据字节数。
     **/
    public void testWritePlcStrData() {

        S7Connector s7Connector = initConnect();
        //第一个参数：DaveArea.DB 表示读取PLC的地址区域为DB
        //第二个参数：DB块地址，若plc中是DB1000，则填1000
        //第三个参数：偏移量
        //第四个参数：写入的数据 二进制数组byte[]  ,总长度为10的话，有效数据只能是10-8，第一位代表总长，第二位，代表有效数据字节
        String str = "59";
        int writeStrLength=10;//地址块大小
        byte[] writeBytes=new byte[writeStrLength];
        writeBytes[0]=(byte)writeStrLength;//写入本字符串块总宽度
        str=str.trim();//清除掉两边的空串
        int availableEffectCharLength=0;//有效字符数控制
        if(str.length()>writeStrLength-2)
        {//>writeStrLength-2 截断到最大有效数据位
            availableEffectCharLength=writeStrLength-2;

        }else{//<=writeStrLength-2
            availableEffectCharLength=str.length();
        }
        writeBytes[1]=(byte)availableEffectCharLength;//写入有效字节数
        byte[] strBytes=str.getBytes(StandardCharsets.US_ASCII);
        for(int i=0;i<availableEffectCharLength;i++){
            writeBytes[i+2]=strBytes[i];
        }
        s7Connector.write(DaveArea.DB,150, 20,writeBytes);
        System.out.println("write str:"+(new String(writeBytes)));
        try {
            s7Connector.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    /**
     * 读取PLC中的浮点型float(real 4字节)数据
     * java float : plc Real 4 字节
     * java double : plc LReal 8 字节
     **/
    public void testReadPlcRealData() {

        S7Connector s7Connector = initConnect();
        //第一个参数：DaveArea.DB 表示读取PLC的地址区域为DB
        //第二个参数：DB块地址，若plc中是DB1000，则填1000
        //第三个参数：数据长度
        //第四个参数：偏移量
        //byte [] bytes = ByteBuffer.allocate(8).putDouble(1729.1729).array();
        //byte [] bytes = { 64, -101, 4, -79, 12, -78, -107, -22 };
        //System.out.println();

        byte[] getBytes = s7Connector.read(DaveArea.DB, 150, 4, 64);
        Float getValue = ByteBuffer.wrap(getBytes).getFloat();
        System.out.println("getFloatData:"+getValue);
        try {
            s7Connector.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    /**
     * 读取PLC中的浮点型Double(8字节)数据
     * java float : plc Real 4 字节
     * java double : plc LReal 8 字节
     **/
    public void testReadPlcLRealData() {

        S7Connector s7Connector = initConnect();
        //第一个参数：DaveArea.DB 表示读取PLC的地址区域为DB
        //第二个参数：DB块地址，若plc中是DB1000，则填1000
        //第三个参数：数据长度
        //第四个参数：偏移量
        //byte [] bytes = ByteBuffer.allocate(8).putDouble(1729.1729).array();
        //byte [] bytes = { 64, -101, 4, -79, 12, -78, -107, -22 };
        //System.out.println();

        byte[] getBytes = s7Connector.read(DaveArea.DB, 6, 8, 4);
        Double getValue = ByteBuffer.wrap(getBytes).getDouble();
        System.out.println("getDoubleData:"+getValue);
        try {
            s7Connector.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    /**
     * 写入PLC中的浮点型数据
     * java float : plc Real 4 字节
     * java double : plc LReal 8 字节
     **/
    public void testWritePlcRealData() {

        S7Connector s7Connector = initConnect();
        //第一个参数：DaveArea.DB 表示读取PLC的地址区域为DB
        //第二个参数：DB块地址，若plc中是DB1000，则填1000
        //第三个参数：偏移量
        //第四个参数：写入的数据 二进制数组byte[]
        float data=new Float(5.54);
        byte[] bytes = ByteBuffer.allocate(4).putFloat(data).array();
        System.out.println("bytes length:"+bytes.length);
        s7Connector.write(DaveArea.DB,150, 64,bytes);
        try {
            s7Connector.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    /**
     * 写入PLC中的浮点型LREAL(java中是double)数据
     * java float : plc Real 4 字节
     * java double : plc LReal 8 字节
     **/
    public void testWritePlcLRealData() {

        S7Connector s7Connector = initConnect();
        //第一个参数：DaveArea.DB 表示读取PLC的地址区域为DB
        //第二个参数：DB块地址，若plc中是DB1000，则填1000
        //第三个参数：偏移量
        //第四个参数：写入的数据 二进制数组byte[]
        float data=new Float(15.5);
        byte[] bytes = ByteBuffer.allocate(8).putDouble(data).array();
        System.out.println("bytes length:"+bytes.length);
        s7Connector.write(DaveArea.DB,6, 4,bytes);
        try {
            s7Connector.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}
